package com.charging.business.vo.obj;

import com.alibaba.fastjson2.annotation.JSONField;
import com.charging.business.enums.Issuer;
import com.charging.business.utils.PayUtil;
import com.charging.business.vo.OnlineSpececResponse;
import lombok.Data;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * @author JerryLu
 * @date 2024/9/26 17:24
 * @description 在线计费结果
 */
@Data
public class OnlineFeeInfo {
    /**
     * 特情计费结果
     * 必填：是
     * 0-网络访问异常,默认值
     * 1-特情计费成功
     * 2-入口站有误-路径不可达
     * 3-路径信息不可拟合-请使用其他拟合方式
     * 4-拟合超时-请使用其他拟合方式
     * 5-非跨省通行
     * 99~90 - 自定义必要字段校验失败
     * 100 - 报文解析失败
     */
    @JSONField(ordinal = 0)
    public Integer calculateResult = 0;

    /**
     * 总应收金额, 单位：分
     * 各省应收总金额累计。payFee=splitAmount+discountFee
     * 必填：是
     */
    @JSONField(ordinal = 1)
    public Integer payFee = 0;

    /**
     * 总实收金额
     * 单位：分。各省实收总金额累计。参考值，不可用于结算
     * 必填：是
     */
    @JSONField(ordinal = 2)
    public Integer fee = 0;

    /**
     * 总优惠金额
     * 单位：分。各省优惠总金额累计。discountFee=payFee-splitAmount
     * 必填：是
     */
    @JSONField(ordinal = 3)
    public Integer discountFee = 0;

    /**
     * 总拆分金额
     * 单位：分。各省拆分总金额累计，用于现场收费。splitAmount=payFee-discountFee
     * 必填：是
     */
    @JSONField(ordinal = 4)
    public Integer splitAmount = 0;

    /**
     * 总里程
     * 里程总数累计,单位:米
     * 必填：是
     */
    @JSONField(ordinal = 5)
    public Integer feeMileage = 0;

    /**
     * 95折取整
     * 单位：分。转现金或其他支付方式实收总金额
     * 必填：是
     */
    @JSONField(ordinal = 6)
    public Integer roundSplitAmount = 0;

    /**
     * 总优惠取整金额
     * 单位：分。各省优惠总金额取整累计。roundDiscountFee=payFee-roundSplitAmount
     * 必填：是
     */
    @JSONField(ordinal = 7)
    public Integer roundDiscountFee = 0;

    /**
     * 分省金额明细
     * 必填：是
     */
    @JSONField(ordinal = 8)
    public List<SplitProvinceOnLine> splitProvince = new ArrayList<>();

    /**
     * 分省金额明细-转现金|其他支付方式分省明细
     * 必填：是
     */
    @JSONField(ordinal = 9)
    public List<SplitProvinceOnLine> roundSplitProvince = new ArrayList<>();


    @JSONField(serialize = false, deserialize = false)
    public void setSplitProDetail(OnlineSpececResponse res) {
        if (res != null) {
            calculateResult = res.calculateResult;
            payFee = res.payFee;
            fee = res.fee;
            discountFee = res.discountFee;
            splitAmount = res.splitAmount;
            feeMileage = res.feeMileage;
            for (ProvinceFee pf : res.getProvinceFees()) {
                SplitProvinceOnLine sp = new SplitProvinceOnLine();
                sp.provinceId = pf.provinceId;
                sp.payFee = pf.payFee;
                sp.fee = pf.fee;
                sp.discountFee = pf.discountFee;
                sp.splitAmount = pf.splitAmount;
                sp.feeMileage = pf.feeMileage;
                sp.tollIntervalsCount = pf.tollIntervalsCount;
                sp.oriIntervalsGroup = pf.oriintervalsGroup;
                sp.tollIntervalsGroup = pf.tollIntervalsGroup;
                sp.transTimeGroup = pf.transTimeGroup;
                sp.feeGroup = pf.feeGroup;
                sp.discountFeeGroup = pf.discountFeeGroup;

                SplitProvinceOnLine sp1 = new SplitProvinceOnLine();
                sp1.provinceId = pf.provinceId;
                sp1.payFee = pf.payFee;
                sp1.fee = pf.fee;
                sp1.discountFee = pf.discountFee;
                sp1.splitAmount = PayUtil.round100(pf.splitAmount);
                sp1.feeMileage = pf.feeMileage;
                sp1.tollIntervalsCount = pf.tollIntervalsCount;
                sp1.oriIntervalsGroup = pf.oriintervalsGroup;
                sp1.tollIntervalsGroup = pf.tollIntervalsGroup;
                sp1.transTimeGroup = pf.transTimeGroup;
                sp1.feeGroup = pf.feeGroup;
                sp1.discountFeeGroup = pf.discountFeeGroup;

                splitProvince.add(sp);
                roundSplitProvince.add(sp1);
            }
        }
    }

    /**
     * 合并分省信息
     */
    @JSONField(serialize = false, deserialize = false)
    public void merge() {
        // 2个及以上
        if (splitProvince.size() > 1) {
            Map<Integer, SplitProvinceOnLine> provs = new LinkedHashMap<>();
            for (SplitProvinceOnLine src : splitProvince) {
                SplitProvinceOnLine mer = provs.get(src.provinceId);
                if (mer == null) {
                    provs.put(src.provinceId, src);
                } else {
                    mer.payFee += src.payFee;
                    mer.fee += src.fee;
                    mer.discountFee += src.discountFee;
                    mer.splitAmount += src.splitAmount;
                    mer.feeMileage += src.feeMileage;
                    mer.tollIntervalsCount += src.tollIntervalsCount;
                    mer.oriIntervalsGroup += "|" + src.oriIntervalsGroup;
                    mer.tollIntervalsGroup += "|" + src.tollIntervalsGroup;
                    mer.transTimeGroup += "|" + src.transTimeGroup;
                    mer.feeGroup += "|" + src.feeGroup;
                    mer.discountFeeGroup += "|" + src.discountFeeGroup;
                }
            }
            splitProvince.clear();
            for (Integer key : provs.keySet()) {
                splitProvince.add(provs.get(key));
            }
        }

        if (roundSplitProvince.size() > 1) {
            Map<Integer, SplitProvinceOnLine> provsin = new LinkedHashMap<>();
            for (SplitProvinceOnLine src1 : roundSplitProvince) {
                SplitProvinceOnLine mer1 = provsin.get(src1.provinceId);
                if (mer1 == null) {
                    provsin.put(src1.provinceId, src1);
                } else {
                    mer1.payFee += src1.payFee;
                    mer1.fee += src1.fee;
                    mer1.discountFee += src1.discountFee;
                    mer1.splitAmount += src1.splitAmount;
                    mer1.feeMileage += src1.feeMileage;
                    mer1.tollIntervalsCount += src1.tollIntervalsCount;
                    mer1.oriIntervalsGroup += "|" + src1.oriIntervalsGroup;
                    mer1.tollIntervalsGroup += "|" + src1.tollIntervalsGroup;
                    mer1.transTimeGroup += "|" + src1.transTimeGroup;
                    mer1.feeGroup += "|" + src1.feeGroup;
                    mer1.discountFeeGroup += "|" + src1.discountFeeGroup;
                }
            }
            roundSplitProvince.clear();
            for (Integer key : provsin.keySet()) {
                roundSplitProvince.add(provsin.get(key));
            }
        }
    }

    @JSONField(serialize = false, deserialize = false)
    public void setRoundSplitProDetail(String exStationHex) {
        if (exStationHex.startsWith(Issuer.Issue140101.getProvinceCode())) {
            if (fee == splitAmount) {
                roundSplitAmount = PayUtil.round100(fee);
            } else {
                roundSplitAmount = PayUtil.round100(splitAmount);
            }
            roundDiscountFee = Math.max(payFee - roundSplitAmount, 0);
        }
    }

    /**
     * 绿通、联合收割机免费处理
     * 分省信息保持不变
     */
    @JSONField(serialize = false, deserialize = false)
    public void green() {
        fee = 0;
        splitAmount = 0;
        discountFee = payFee;
        payFee = splitAmount + discountFee;
    }

    /**
     * 全免费,清除计费信息
     */
    @JSONField(serialize = false, deserialize = false)
    public void toAllFree() {
        fee = 0;
        discountFee = 0;
        splitAmount = 0;
        if (splitProvince != null) {
            for (SplitProvinceOnLine prov : splitProvince) {
                prov.toFree();
                discountFee += prov.discountFee;
            }
        }
        payFee = splitAmount + discountFee;
        //discountFee=payFee-splitAmount;
        //splitAmount=payFee-discountFee;
    }

    /**
     * 本省免费,清除本省计费信息
     */
    @JSONField(serialize = false, deserialize = false)
    public void toLocalFree() {
        fee = 0;
        discountFee = 0;
        splitAmount = 0;
        for (SplitProvinceOnLine prov : splitProvince) {
            if (prov.provinceId == 14) {
                prov.toFree();    // 本省免费
            }

            fee += prov.fee;
            discountFee += (prov.payFee - prov.splitAmount);
            splitAmount += prov.splitAmount;
        }
        payFee = splitAmount + discountFee;
        //discountFee=payFee-splitAmount;
        //splitAmount=payFee-discountFee;
    }

    /**
     * 获取ETC全程仅95折收费金额
     * 不考虑其他免费及折扣
     * 用于与兜底费进行阈值比较
     * 通过各省计费模块输出的payFee累计值进行计算
     *
     * @param localPayFeeModify - 本省应收修正金额
     * @return
     */
    public int etcSum095Fee(int localPayFeeModify) {
        int other = 0;
        int local = 0;
        for (SplitProvinceOnLine prov : splitProvince) {
            if (prov.provinceId == 14) {
                local += prov.payFee;
            } else {
                other += PayUtil.etcFinalFee(prov.payFee);
            }
        }
        // 本省应收修正
        local += localPayFeeModify;

        return other + PayUtil.etcFinalFee(local);
    }

    /**
     * 计算MTC全程无优惠收费总金额
     * 不考虑其他免费及折扣
     * 用于与兜底费进行阈值比较
     * 通过各省计费模块输出的(fee + discountFee)累计值进行计算
     *
     * @return
     */
    @JSONField(serialize = false, deserialize = false)
    public int mtcSum100Fee() {
        int res = 0;
        for (int aa = 0; aa < splitProvince.size(); aa++) {
            SplitProvinceOnLine row = splitProvince.get(aa);
            res += PayUtil.mtcFinalFee(row.fee + row.discountFee);
        }

        return res;

    }

    /**
     * 计算MTC全程本省免费后收费总金额
     * 本省免费(如本省警车), 外省不考虑其他免费及折扣
     * 用于与兜底费进行阈值比较
     * 通过各省计费模块输出的(fee + discountFee)累计值进行计算
     *
     * @return
     */
    public int mtcSum100FeeAftLFree() {
        int res = 0;
        for (int aa = 0; aa < splitProvince.size(); aa++) {
            SplitProvinceOnLine row = splitProvince.get(aa);
            if (row.provinceId != 14) {// 外省
                res += PayUtil.mtcFinalFee(row.fee + row.discountFee);
            }
        }

        return res;
    }

    /**
     * 获取本省累计应收
     *
     * @return
     */
    @JSONField(serialize = false, deserialize = false)
    public int payFeeProvSumLocal() {
        int res = 0;
        for (SplitProvinceOnLine prov : splitProvince) {
            if (prov.provinceId == 14) {// 本省
                res += prov.payFee;
            }
        }

        return res;
    }

    /**
     * 获取本省累计实收
     *
     * @return
     */
    @JSONField(serialize = false, deserialize = false)
    public int feeProvSumLocal() {
        int res = 0;
        for (SplitProvinceOnLine prov : splitProvince) {
            if (prov.provinceId == 14) {// 本省
                res += prov.splitAmount;
            }
        }

        return res;
    }

    /**
     * 获取本省累计里程
     *
     * @return
     */
    @JSONField(serialize = false, deserialize = false)
    public int feeMileageProvSumLocal() {
        int res = 0;
        for (SplitProvinceOnLine prov : splitProvince) {
            if (prov.provinceId == 14) {// 本省
                res += prov.feeMileage;
            }
        }

        return res;
    }
}
